Generic functions allow you to
specify different arguments list for an abstract function type. This allows the
programmer more flexibility in specifying the argument list for a function.
To give an idea of how these functions are used here
is an example:
double overloaded sqrt(double);
int overloaded sqrt(int);
This declares two different
functions that will get an automatic name furnished by the compiler. Those
functions will be selected at the call site according to their arguments list:
if the argument list is a double, the first function will be called and the
type of the resulting expression is a double. If an integer is given, the
second function will be selected and the resulting type is integer.
The exact syntax is:
Short form:
<return type> overloaded identifier (
argument-list )
Example:
double overloaded sqrt(double);
The compiler will supply here
automatically a name for this function. The name will be constructed from the
overloaded identifier and the argument list.
Long form:
<return type> overloaded identifier .
identifier ( argument-list )
Example:
double overloaded sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);
The long form allows the
programmer to override the automatic name of the function and furnish its own.
This is important since it allows for easy interfacing of the software that
uses this extension with other software.
This extension doesn’t introduce
a new keyword. You can still define
int overloaded = 0;
or
int overloaded(int a);
or even
typedef int *overloaded;
overloaded foo(int a);
and this will compile as you
would expect. In the last example the typedef definition is used, since
overloaded functions can’t have an implicit “int” result: they must be given a full
prototype.
If you need (for whatever reason)
to force the compiler to choose one of the overloaded functions, you should use
the long notation and just call the function in question:
double overloaded
sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);
You can force calling the first
function just with:
double
s = DblSqrt(4.9);
The DblSqrt function will be
visible in the current scope after the “overloaded” declaration is seen.
· You can add any number of overloaded arguments lists to an identifier, but once the first call to such a function is generated, it is impossible to add a new definition.
For instance :
double overloaded sqrt(double);
int overloaded sqrt(int);
int foo(void)
{
double
a = sqrt(2.3);
}
double overloaded
sqrt(complex) ;
This is an error. All overloaded function definitions must be present when the first call is generated.
· You must supply the « overloaded » marker at the declaration and at the definition of the function. For instance, it is an error when you write :
double overloaded sqrt(double) ;
double sqrt(double) // error :
redefinition of sqrt.
{
…
}
This extension is very useful for
constructors. For instance consider:
typedef struct _Person {
char
*Name;
int
Age;
} Person;
Person * overloaded
newPerson(void)
{
return
(Person *)malloc(sizeof(Person));
}
Person *newPerson(char *name)
{
Person
*result = malloc(sizeof(Person));
result->Name
= name;
return
result;
}
Person *newPerson(char *Name,int
age)
{
Person
*result = (Person *)malloc(sizeof(Person));
result->Name
= name;
result->Age
= age;
return
result;
}
etc.